﻿using EventBus.Abstractions;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace EventBus
{
    public class EventHandlerExecutionContext
        : IEventHandlerExecutionContext
    {
        private readonly IServiceCollection _registry;
        private readonly IServiceProvider _sp;
        private readonly Func<IServiceCollection, IServiceProvider> _factory;

        private Dictionary<Type, List<Type>> _registrations = new Dictionary<Type, List<Type>>();
        public EventHandlerExecutionContext(IServiceCollection registry, Func<IServiceCollection, IServiceProvider> factory = null)
        {
            _registry = registry;
            _sp = _registry.BuildServiceProvider();
            _factory = factory;
        }
        public async Task<bool> HandleAsync<TEvent>(TEvent @event) where TEvent : IEvent
        {
            _registrations.TryGetValue(typeof(TEvent), out List<Type> registerItems);
            foreach (var item in registerItems)
            {
                using (var scope = _sp.CreateScope())
                {
                    var handler = Activator.CreateInstance(item) as IEventHandler;
                    await handler.HandleAsync(@event);
                }
            }
            return true;
        }

        public bool IsRegisteEventHandler<TEvent, TEventHandler>()
            where TEvent : IEvent
            where TEventHandler : IEventHandler
        {
            if (_registrations.TryGetValue(typeof(TEvent), out List<Type> registerItems))
            {
                return registerItems != null && registerItems.Any() && registerItems.Contains(typeof(TEventHandler));
            }
            return false;
        }

        public void RegisteEventHandler<TEvent, TEventHandler>()
            where TEvent : IEvent
            where TEventHandler : IEventHandler
        {
            if (_registrations.TryGetValue(typeof(TEvent), out List<Type> registerItems))
            {
                if (registerItems != null)
                {
                    if (!registerItems.Contains(typeof(TEventHandler)))
                    {
                        registerItems.Add(typeof(TEventHandler));
                    }
                }
                else
                {
                    _registrations[typeof(TEvent)] = new List<Type>() { typeof(TEventHandler) };
                }
            }
            else
            {
                _registrations.TryAdd(typeof(TEvent), new List<Type>() { typeof(TEventHandler) });
            }
        }
    }
}
